package socks

import (
	"io"
	"sync"

	"gitee.com/cjianwen/go/memo"
)

type SendQueue struct {
	mu        sync.Mutex
	dataLists [][]byte
	lastDatas []byte
	writeLen  int
}

func (s *SendQueue) Write(b []byte) (n int, e error) {
	s.mu.Lock()
	defer s.mu.Unlock()
	idx := 0
	bLen := len(b)
	var cn int
	for idx < bLen {
		if s.writeLen >= len(s.lastDatas) {
			s.lastDatas = memo.PoolGet_cap(bLen)
			s.writeLen = 0
			s.dataLists = append(s.dataLists, s.lastDatas)
		}
		wrtLen := len(s.lastDatas) - s.writeLen
		lftLen := bLen - idx
		if wrtLen > lftLen {
			wrtLen = lftLen
		}
		cn = copy(s.lastDatas[s.writeLen:], b[idx:idx+wrtLen])
		idx += cn
		n += cn
		s.writeLen += cn
	}
	return
}

func (s *SendQueue) WriteTo(w io.Writer) (n int64, e error) {
	s.mu.Lock()
	datas := s.dataLists
	s.dataLists = nil
	s.lastDatas = nil
	s.writeLen = 0
	s.mu.Unlock()

	for _, v := range datas {
		if e == nil {
			if wn, err := w.Write(v); err != nil {
				e = err
			} else {
				n += int64(wn)
			}
		}
		memo.PoolPut(v)
	}
	return
}

func (s *SendQueue) Clear() {
	s.mu.Lock()
	datas := s.dataLists
	s.dataLists = nil
	s.lastDatas = nil
	s.writeLen = 0
	s.mu.Unlock()

	for _, v := range datas {
		memo.PoolPut(v)
	}
}
